﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace MDSAdministration
{
    /// <summary>
    /// Interaction logic for BuildDataCompare.xaml
    /// </summary>
    public partial class BuildDataCompare : Window
    {
        private static BackgroundWorker bw;
        public static Dictionary<String, Dictionary<String, EntityColumn>> dDataCompareMetaData;
        public static DataSet dsDataCompare;
        public static ServerMDSDetails ServerA;
        public static ServerMDSDetails ServerB;
        public static Dictionary<string, EntityDataCompreDetails> EntityDetails;
        public static bool OnlyEntityDetails;
        public static EntityDataCompreDetails EntityDataCompreDetail;
        public static ServerDirection sDirection;
        public static CheckStates cStates;

        public static string EntityName;
        public static int TotalCount;
        public static int EntityIndex;
        public bool DoWork { get; set; }
        public BuildDataCompare()
        {
            InitializeComponent();

        }

        public string ProgressMessage
        {
            set { lblMessage.Content = value; }
            get { return lblMessage.Content.ToString(); }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            bw = new BackgroundWorker();

            bw.WorkerReportsProgress = true;
            bw.WorkerSupportsCancellation = true;

            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

            bw.RunWorkerAsync();

        }


        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            var eData = new EntityData() { ServerA = ServerA, ServerB = ServerB, cStates = cStates };
            eData.Changed += new ChangedEventHandler(eData_Changed);

            if (DoWork)
            {
                BackgroundWorker bWorker = sender as BackgroundWorker;

                bWorker.ReportProgress(0, "Starting Entity List Build");

                dsDataCompare.Tables.Clear();
                dDataCompareMetaData.Clear();

                EntityDetails = eData.GetEntityList(sDirection);

                if (OnlyEntityDetails == false)
                {
                    TotalCount = EntityDetails.Count;
                    EntityIndex = 0;

                    foreach (var ed in EntityDetails.Values)
                    {
                        if ((bWorker.CancellationPending == true))
                        {
                            e.Cancel = true;
                            break;
                        }

                        EntityIndex++;
                        EntityName = ed.Name;

                        GetEntityData(eData, ed);
                    }
                }
            }
            else
            {
                GetEntityData(eData, EntityDataCompreDetail);
            }
        }

        public static void GetEntityData(EntityData eData, EntityDataCompreDetails ed)
        {
            DataSet ds = eData.GetEntityData(ed);

            if (ds == null)
            {
                ed.Match = false;
                return;
            }

            ed.Match = true;
            ed.Processed = true;

            dDataCompareMetaData.Add(ed.Name, eData.EntityColumns);

            if (ds.Tables.Count > 0)
            {
                ds.Tables[0].TableName = ed.Name;
                DataTable dt = ds.Tables[0].Copy();
                dsDataCompare.Tables.Add(dt);

                ed.TotalCount = dt.Rows.Count;

                ed.OnlyOnACount = (from r in dt.AsEnumerable()
                                   where r.Field<string>("servA_Code") != null &&
                                   r.Field<string>("servB_Code") == null
                                   select r).Count();

                ed.OnlyOnBCount = (from r in dt.AsEnumerable()
                                   where r.Field<string>("servB_Code") != null &&
                                   r.Field<string>("servA_Code") == null
                                   select r).Count();

                ed.SameCount = (from r in dt.AsEnumerable()
                                where r.Field<string>(Constants.MDSADMINISTRATION_SERVA + Constants.MDSADMINISTRATION_CODE) == r.Field<string>(Constants.MDSADMINISTRATION_SERVB + Constants.MDSADMINISTRATION_CODE)
                                && r.Field<string>(Constants.MDSADMINISTRATION_SERVA + Constants.MDSADMINISTRATION_HASHCODE) == r.Field<string>(Constants.MDSADMINISTRATION_SERVB + Constants.MDSADMINISTRATION_HASHCODE)
                                select r).Count();

                ed.DiffernetCount = (from r in dt.AsEnumerable()
                                     where
                                         r.Field<string>(Constants.MDSADMINISTRATION_SERVA + Constants.MDSADMINISTRATION_HASHCODE) != r.Field<string>(Constants.MDSADMINISTRATION_SERVB + Constants.MDSADMINISTRATION_HASHCODE)
                                         || r.Field<string>(Constants.MDSADMINISTRATION_SERVA + Constants.MDSADMINISTRATION_HASHCODE) != r.Field<string>(Constants.MDSADMINISTRATION_SERVB + Constants.MDSADMINISTRATION_HASHCODE)
                                     select r).Count();
            }
        }

        void eData_Changed(object sender, string message)
        {
            if (DoWork)
            {
                bw.ReportProgress(EntityIndex, EntityIndex.ToString() + "/" + TotalCount.ToString() + " " + message);
            }
            else
            {
                bw.ReportProgress(EntityIndex, message);
            }
        }

        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            ProgressMessage = e.UserState.ToString();
        }

        public Exception Error;

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!(e.Error == null))
            {
                Error = e.Error;
            }

            Close();
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            if (bw.WorkerSupportsCancellation == true)
            {
                bw.CancelAsync();
                ProgressMessage = "Wait for last process to complete.";
            }
        }
    }
}
